package com.kongjs.application.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kongjs.application.convert.MenusConverter;
import com.kongjs.application.mapper.MenusMapper;
import com.kongjs.application.model.dto.*;
import com.kongjs.application.model.entity.Menus;
import com.kongjs.application.model.entity.RoleMenu;
import com.kongjs.application.service.IMenuMetaService;
import com.kongjs.application.service.IMenusService;
import com.kongjs.application.service.IRoleMenuService;
import com.kongjs.common.rest.util.JsonUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;


@Transactional
@Service
public class MenusServiceImpl extends ServiceImpl<MenusMapper, Menus> implements IMenusService {
    @Resource
    private MenusConverter menusConverter;
    @Resource
    private IMenuMetaService menuMetaService;
    @Resource
    private IRoleMenuService roleMenuService;

    public boolean save(SaveMenuDTO dto) {
        Menus entity = menusConverter.toEntity(dto);
        if (!ObjectUtils.isEmpty(dto.getMeta())) {
            String json = JsonUtils.toJson(dto.getMeta());
            entity.setMeta(json);
        }
        this.save(entity);
        /*
        if (!CollectionUtils.isEmpty(dto.getMeta())) {
            List<MenuMeta> metas = new ArrayList<>();
            for (Map.Entry<String, Object> entry : dto.getMeta().entrySet()) {
                if (ObjectUtils.isEmpty(entry.getValue())) {
                    continue;
                }
                MenuMeta meta = new MenuMeta();
                meta.setMenuId(entity.getId());
                meta.setMetaKey(entry.getKey());
                meta.setMetaValue(entry.getValue().toString());
                metas.add(meta);
            }
            menuMetaService.saveBatch(metas);
        }
        */
        return true;
    }

    @Override
    public boolean remove(Serializable id) {
        removeById(id);
        /*
        menuMetaService.lambdaUpdate()
                .eq(MenuMeta::getMenuId, id)
                .remove();
        */
        roleMenuService.lambdaUpdate()
                .eq(RoleMenu::getMenuId, id)
                .remove();
        return true;
    }

    @Override
    public boolean update(UpdateMenuDTO dto) {
        Menus entity = menusConverter.toEntity(dto);
        if (!ObjectUtils.isEmpty(dto.getMeta())) {
            String json = JsonUtils.toJson(dto.getMeta());
            entity.setMeta(json);
        }
        this.updateById(entity);
        /*
        if (!CollectionUtils.isEmpty(dto.getMeta())) {
            menuMetaService.lambdaUpdate()
                    .eq(MenuMeta::getMenuId, entity.getId())
                    .remove();
            List<MenuMeta> metas = new ArrayList<>();
            for (Map.Entry<String, Object> entry : dto.getMeta().entrySet()) {
                if (ObjectUtils.isEmpty(entry.getValue())) {
                    continue;
                }
                MenuMeta meta = new MenuMeta();
                meta.setMenuId(entity.getId());
                meta.setMetaKey(entry.getKey());
                meta.setMetaValue(entry.getValue().toString());
                metas.add(meta);
            }
            menuMetaService.saveBatch(metas);
        }
        */
        return true;
    }

    @Override
    public List<QueryMenuDTO> queryList() {
        /*
        Map<Long, List<MenuMeta>> metaMap = menuMetaService.list()
                .stream()
                .collect(Collectors.groupingBy(MenuMeta::getMenuId));
        */
        return this.lambdaQuery()
                .orderByAsc(Menus::getMenuSort)
                .list()
                .stream().map(entity -> {
                    QueryMenuDTO dto = menusConverter.toDto(entity);
                    QueryMenuMetaDTO metaDTO = JsonUtils.fromJson(entity.getMeta(), QueryMenuMetaDTO.class);
                    dto.setMeta(metaDTO);
            /*
            List<MenuMeta> metas = metaMap.get(dto.getId());
            if (!CollectionUtils.isEmpty(metas)) {
                Map<String, Object> map = new HashMap<>();
                for (MenuMeta meta : metas) {
                    map.put(meta.getMetaKey(), meta.getMetaValue());
                }
                dto.setMeta(map);
            }
            */
                    return dto;
                }).toList();
    }

    @Override
    public List<QueryMenuDTO> trees() {
        return this.lambdaQuery()
                .eq(Menus::getEnabled, 1)
                .orderByAsc(Menus::getMenuSort)
                .list()
                .stream().map(entity -> {
                    QueryMenuDTO dto = menusConverter.toDto(entity);
                    QueryMenuMetaDTO metaDTO = JsonUtils.fromJson(entity.getMeta(), QueryMenuMetaDTO.class);
                    dto.setMeta(metaDTO);
                    return dto;
                }).toList();
    }

    public boolean exists(MenuExistsDTO dto) {
        LambdaQueryWrapper<Menus> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtils.isEmpty(dto.getId())) {
            wrapper
                    .eq(StringUtils.hasText(dto.getMenuName()), Menus::getMenuName, dto.getMenuName())
                    .eq(StringUtils.hasText(dto.getMenuPath()), Menus::getMenuPath, dto.getMenuPath());
            return count(wrapper) >= 1;
        }
        wrapper
                .eq(!ObjectUtils.isEmpty(dto.getId()), Menus::getId, dto.getId())
                .eq(StringUtils.hasText(dto.getMenuName()), Menus::getMenuName, dto.getMenuName())
                .eq(StringUtils.hasText(dto.getMenuPath()), Menus::getMenuPath, dto.getMenuPath());
        return !(count(wrapper) <= 1);
    }
}
